<?php
/***
* @version $Id: functions_install.php 336 2007-01-23 08:12:56Z flexiondotorg $
* @copyright (c) 2006 - 2007 Flexion.Org
*            (c) 2004 - 2005 Project Minerva
*            (c) 2001 - 2006 phpBB Group
* @license   http://opensource.org/licenses/gpl-license.php GNU Public License
***/

if ( !defined('IN_R3BORN') )
{
	die('Hacking attempt');
}

/*
* The functions here are really only used for core, block and module installs and updates.
*/
global $available_dbms;

// Supported DB layers including relevant details
$available_dbms = array(
	'mysql'		=> array(
		'LABEL'			=> 'MySQL 3.23.x',
		'SCHEMA'		=> 'mysql',
		'MODULE'		=> 'mysql',
		'DELIM'			=> ';',
		'DELIM_BASIC'	=> ';',
		'COMMENTS'		=> 'remove_remarks'
	),
	'mysql4'	=> array(
		'LABEL'			=> 'MySQL 4.x/5.x',
		'SCHEMA'		=> 'mysql',
		'MODULE'		=> 'mysql',
		'DELIM'			=> ';',
		'DELIM_BASIC'	=> ';',
		'COMMENTS'		=> 'remove_remarks'
	),
	/*'mysqli'	=> array(
		'LABEL'			=> 'MySQLi 4.1.x/5.x (MySQLi)',
		'SCHEMA'		=> 'mysql',
		'MODULE'		=> 'mysqli',
		'DELIM'			=> ';',
		'DELIM_BASIC'	=> ';',
		'COMMENTS'		=> 'remove_remarks'
	),*/
	'mssql'		=> array(
		'LABEL'			=> 'MS SQL Server 7/2000',
		'SCHEMA'		=> 'mssql',
		'MODULE'		=> 'mssql',
		'DELIM'			=> 'GO',
		'DELIM_BASIC'	=> ';',
		'COMMENTS'		=> 'remove_comments'
	),
	'mssql_odbc'=>	array(
		'LABEL'			=> 'MS SQL Server [ ODBC ]',
		'SCHEMA'		=> 'mssql',
		'MODULE'		=> 'odbc',
		'DELIM'			=> 'GO',
		'DELIM_BASIC'	=> ';',
		'COMMENTS'		=> 'remove_comments'
	),
	'postgres' => array(
		'LABEL'			=> 'PostgreSQL 7.x',
		'SCHEMA'		=> 'postgres',
		'MODULE'		=> 'pgsql',
		'DELIM'			=> ';',
		'DELIM_BASIC'	=> ';',
		'COMMENTS'		=> 'remove_comments'
	),
	/*
	'firebird' =>	array(
		'LABEL'			=> 'Firebird 1.5',
		'SCHEMA'		=> 'firebird',
		'MODULE'		=> 'interbase',
		'DELIM'			=> ';',
		'DELIM_BASIC'	=> ';',
		'COMMENTS'		=> 'remove_comments'
	)
	*/
	/*
	'oracle'	=>	array(
		'LABEL'			=> 'Oracle',
		'SCHEMA'		=> 'oracle',
		'MODULE'		=> 'oci8',
		'DELIM'			=> '/',
		'DELIM_BASIC'	=> ';',
		'COMMENTS'		=> 'remove_comments'
	),*/
	/*
	'sqlite'		=> array(
		'LABEL'			=> 'SQLite',
		'SCHEMA'		=> 'sqlite',
		'MODULE'		=> 'sqlite',
		'DELIM'			=> ';',
		'DELIM_BASIC'	=> ';',
		'COMMENTS'		=> 'remove_remarks'
	),*/
);

//
// remove_comments will strip the sql comment lines out of an uploaded sql file
// specifically for mssql and postgres type files in the install....
//
function remove_comments(&$output)
{
	$lines = explode("\n", $output);
	$output = "";

	// try to keep mem. use down
	$linecount = count($lines);

	$in_comment = false;
	for($i = 0; $i < $linecount; $i++)
	{
		if( preg_match("/^\/\*/", preg_quote($lines[$i])) )
		{
			$in_comment = true;
		}

		if( !$in_comment )
		{
			$output .= $lines[$i] . "\n";
		}

		if( preg_match("/\*\/$/", preg_quote($lines[$i])) )
		{
			$in_comment = false;
		}
	}

	unset($lines);
	return $output;
}

//
// remove_remarks will strip the sql comment lines out of an uploaded sql file
//
function remove_remarks($sql)
{
	$lines = explode("\n", $sql);

	// try to keep mem. use down
	$sql = "";

	$linecount = count($lines);
	$output = "";

	for ($i = 0; $i < $linecount; $i++)
	{
		if (($i != ($linecount - 1)) || (strlen($lines[$i]) > 0))
		{
			if ($lines[$i][0] != "#")
			{
				$output .= $lines[$i] . "\n";
			}
			else
			{
				$output .= "\n";
			}
			// Trading a bit of speed for lower mem. use here.
			$lines[$i] = "";
		}
	}

	return $output;

}

//
// split_sql_file will split an uploaded sql file into single sql statements.
// Note: expects trim() to have already been run on $sql.
function split_sql_file($sql, $delimiter)
{
	// Split up our string into "possible" SQL statements.
	$tokens = explode($delimiter, $sql);

	// try to save mem.
	$sql = "";
	$output = array();

	// we don't actually care about the matches preg gives us.
	$matches = array();

	// this is faster than calling count($oktens) every time thru the loop.
	$token_count = count($tokens);
	for ($i = 0; $i < $token_count; $i++)
	{
		// Don't wanna add an empty string as the last thing in the array.
		if (($i != ($token_count - 1)) || (strlen($tokens[$i] > 0)))
		{
			// This is the total number of single quotes in the token.
			$total_quotes = preg_match_all("/'/", $tokens[$i], $matches);
			// Counts single quotes that are preceded by an odd number of backslashes,
			// which means they're escaped quotes.
			$escaped_quotes = preg_match_all("/(?<!\\\\)(\\\\\\\\)*\\\\'/", $tokens[$i], $matches);

			$unescaped_quotes = $total_quotes - $escaped_quotes;

			// If the number of unescaped quotes is even, then the delimiter did NOT occur inside a string literal.
			if (($unescaped_quotes % 2) == 0)
			{
				// It's a complete sql statement.
				$output[] = $tokens[$i];
				// save memory.
				$tokens[$i] = "";
			}
			else
			{
				// incomplete sql statement. keep adding tokens until we have a complete one.
				// $temp will hold what we have so far.
				$temp = $tokens[$i] . $delimiter;
				// save memory..
				$tokens[$i] = "";

				// Do we have a complete statement yet?
				$complete_stmt = false;

				for ($j = $i + 1; (!$complete_stmt && ($j < $token_count)); $j++)
				{
					// This is the total number of single quotes in the token.
					$total_quotes = preg_match_all("/'/", $tokens[$j], $matches);
					// Counts single quotes that are preceded by an odd number of backslashes,
					// which means they're escaped quotes.
					$escaped_quotes = preg_match_all("/(?<!\\\\)(\\\\\\\\)*\\\\'/", $tokens[$j], $matches);

					$unescaped_quotes = $total_quotes - $escaped_quotes;

					if (($unescaped_quotes % 2) == 1)
					{
						// odd number of unescaped quotes. In combination with the previous incomplete
						// statement(s), we now have a complete statement. (2 odds always make an even)
						$output[] = $temp . $tokens[$j];

						// save memory.
						$tokens[$j] = "";
						$temp = "";

						// exit the loop.
						$complete_stmt = true;
						// make sure the outer loop continues at the right point.
						$i = $j;
					}
					else
					{
						// even number of unescaped quotes. We still don't have a complete statement.
						// (1 odd and 1 even always make an odd)
						$temp .= $tokens[$j] . $delimiter;
						// save memory.
						$tokens[$j] = "";
					}

				} // for..
			} // else
		}
	}

	return $output;
}

function _sql($sql, &$errored, &$error_ary, $echo_dot = true)
{
	global $db;

	if (!($result = $db->sql_query($sql)))
	{
		$errored = true;
		$error_ary['sql'][] = $sql;
		$error_ary['error_code'][] = $db->sql_error();
	}

	if ($echo_dot)
	{
		echo ". \n";
		flush();
	}

	return $result;
}

// Output page -> header
function inst_page_header($title)
{
	global $phpEx, $lang;

?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php echo $lang['ENCODING']; ?>" lang="<?php echo $lang['ENCODING']; ?>" dir="<?php echo $lang['DIRECTION'] ?>">
<head>
<title><?php echo $title; ?></title>
<link href="../templates/subAndreas/subAndreas.css" rel="stylesheet" type="text/css" media="screen" />
</head>
<body>
	<div id="wrap">
		<div id="header">
			<h1><a name="top"><?php echo $title; ?></a></h1>
		</div>

		<div id="navigation">
			&nbsp;
		</div>

   		<table border="0" width="100%" cellpadding="2" cellspacing="2">
        	<tr>
				<td valign="top">
<?php
}

// Output page -> footer
function inst_page_footer()
{
	global $db;
?>
				</td>
			</tr>
		</table>

		<div id="footer">
		    <p class="gensmall">Powered by R3-Born &copy; <?php echo date('Y'); ?> <a href="http://www.flexion.org/" target="_blank">Flexion.Org</a>.</p>
		</div>
	</div>
</body>
</html>
<?php
if (!empty($db))
{
	$db->sql_close();
}
}

function install_die($message)
{
	inst_page_header();
	echo '<h1>Error</h1>' . "\n";
	echo '<p>' . $message . '</p>';
	inst_page_footer();
	exit;
}

function inst_db_error($error, $sql, $line, $file)
{
	global $lang, $db;

	inst_page_header();

?>

<h1 style="color:red;text-align:center"><?php echo $lang['INST_ERR_FATAL']; ?></h1>

<p><?php echo $lang['INST_ERR_FATAL_DB']; ?></p>

<p><?php echo "$file [ $line ]"; ?></p>

<p>SQL : <?php echo $sql; ?></p>

<p><b><?php echo $error; ?></b></p>

<?php

	inst_page_footer();
	exit;
}

function inst_language_select($default = '')
{
	global $root_path, $phpEx;

	$dirname = $root_path . 'language';
	$dir = opendir($dirname);

	$lang_options = array();
	while ($file = readdir($dir))
	{
		if (preg_match('#^lang_#i', $file) && !is_file(@realpath($dirname . '/' . $file)) && !is_link(@realpath($dirname . '/' . $file)))
		{
			$filename = trim(str_replace('lang_', '', $file));
			$displayname = preg_replace('/^(.*?)_(.*)$/', '\1 [ \2 ]', $filename);
			$displayname = preg_replace('/\[(.*?)_(.*)\]/', '[ \1 - \2 ]', $displayname);
			$lang_options[$displayname] = $filename;
		}
	}

	closedir($dir);

	@asort($lang_options);
	@reset($lang_options);

	$user_select = '';
	foreach ($lang_options as $displayname => $filename)
	{
		$selected = (strtolower($default) == strtolower($filename)) ? ' selected="selected"' : '';
		$user_select .= '<option value="' . $filename . '"' . $selected . '>' . ucwords($displayname) . '</option>';
	}

	return $user_select;
}

function can_load_dll($dll)
{
	global $suffix;

	return ((@ini_get('enable_dl') || strtolower(@ini_get('enable_dl')) == 'on') && (!@ini_get('safe_mode') || strtolower(@ini_get('safe_mode')) == 'off') && @dl($dll . ".$suffix")) ? true : false;
}

function connect_check_db($error_connect, &$error, &$dbms, &$table_prefix, &$dbhost, &$dbuser, &$dbpasswd, &$dbname, &$dbport)
{
	global $root_path, $phpEx, $config, $lang;

	// Include the DB layer
	require($root_path . 'includes/db/' . $dbms . '.' . $phpEx);

	// Instantiate it and set return on error true
	//$sql_db = 'dbal_' . $dbms;
	//$db = new $sql_db();
	//$db->sql_return_on_error(true);

	// Try and connect ...
	//if (is_array($db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false)))
	//{
	//	$db_error = $db->sql_error();
	//	$error['db'][] = $lang['INST_ERR_DB_CONNECT'] . '<br />' . (($db_error['message']) ? $db_error['message'] : $lang['INST_ERR_DB_NO_ERROR']);
	//}

	$db = new sql_db($dbhost, $dbuser, $dbpasswd, $dbname, false);
	if(!$db->db_connect_id)
	{
		$db_error = $db->sql_error();
		$error['db'][] = $lang['INST_ERR_DB_CONNECT'] . '<br />' . (($db_error['message']) ? $db_error['message'] : $lang['INST_ERR_DB_NO_ERROR']);
	}
	else
	{
		switch ($dbms)
		{
			case 'mysql':
			case 'mysql4':
			case 'mysqli':
			case 'sqlite':
				$sql = "SHOW TABLES";
				$field = "Tables_in_{$dbname}";
				break;

			case 'mssql':
			case 'mssql_odbc':
				$sql = "SELECT name
					FROM sysobjects
					WHERE type='U'";
				$field = "name";
				break;

			case 'postgres':
				$sql = "SELECT relname
					FROM pg_class
					WHERE relkind = 'r'
						AND relname NOT LIKE 'pg\_%'";
				$field = "relname";
				break;

			case 'firebird':
				$sql = 'SELECT rdb$relation_name
					FROM rdb$relations
					WHERE rdb$view_source is null
						AND rdb$system_flag = 0';
				$field = 'rdb$relation_name';
				break;

			case 'oracle':
				$sql = 'SELECT table_name FROM USER_TABLES';
				$field = 'table_name';
				break;
		}
		$result = $db->sql_query($sql);

		if ($row = $db->sql_fetchrow($result))
		{
			// Likely matches for an existing installation
			$table_ary = array($table_prefix . 'config', $table_prefix . 'sessions', $table_prefix . 'users');

			do
			{
				// All installations will at least have config else it won't
				// work
				if (in_array(strtolower($row[$field]), $table_ary))
				{
					$error['db'][] = $lang['INST_ERR_PREFIX'];
					break;
				}
			}
			while ($row = $db->sql_fetchrow($result));
		}
		$db->sql_freeresult($result);

		$db->sql_close();
	}

	if ($error_connect && (!isset($error['db']) || !sizeof($error['db'])))
	{
		$error['db'][] = $lang['INST_ERR_DB_NO_ERROR'];
	}
}

?>